package com.itheima.service.db.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.db.UserTopic;
import com.itheima.mapper.TestSoulMapper;
import com.itheima.mapper.UserTopicMapper;
import com.itheima.service.db.OptionSoulService;
import com.itheima.service.db.QuestionForSoulService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserTopicService;
import com.itheima.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static com.itheima.constants.Constant.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserTopicServiceImpl extends ServiceImpl<UserTopicMapper, UserTopic> implements UserTopicService {

    private final OptionSoulService optionSoulService;

    private final QuestionForSoulService questionForSoulService;

    private final TestSoulMapper testSoulMapper;

    private final UserInfoService userInfoService;

    @Override
    public Long submit(AnswersVo answersVo) {
        //取出当前登录用户id
        Long id= answersVo.getUserId();

        //算总分
        List<Answers> answers = answersVo.getAnswers();
        //根据问题id和选项id查出对应的分数
        int totalScore = 0;
        for (Answers answer : answers) {
            String questionId = answer.getQuestionId();
            String optionId = answer.getOptionId();
            Integer score = optionSoulService.findScoreById(questionId, optionId);
            if (score != null) {
                totalScore += score;
            }
        }
        UserTopic userTopic = new UserTopic();
        userTopic.setUserId(id);
        userTopic.setScore(totalScore);
        //根据不同的总分给出不同的结果
        if(totalScore < 21){
            userTopic.setResultId(1L);
        }else if(totalScore < 41){
            userTopic.setResultId(2L);
        }else if(totalScore < 56){
            userTopic.setResultId(3L);
        }else {
            userTopic.setResultId(4L);
        }

        //维度占比 =维度得分合计 / 维度最高分合计
        //初始化4个维度总得分
        int d1 = 0;
        int d2 = 0;
        int d3 = 0;
        int d4 = 0;
        //计算4个维度各自的总得分
        for (Answers a : answers) {
            String questionId = a.getQuestionId();
            String optionId = a.getOptionId();
            //找每道题对应的维度类型
            int d = questionForSoulService.findDimensionalityById(questionId);
            //根据问题id和选项id查出当前题获得的分数
            Integer score = optionSoulService.findScoreById(questionId, optionId);
            //根据维度类型赋予对应的得分
            switch (d){
                case 1:
                    d1 += score;
                    break;
                case 2:
                    d2 += score;
                    break;
                case 3:
                    d3 += score;
                    break;
                case 4:
                    d4 += score;
                    break;
            }
        }

        //初始化4个维度最高分的总分
        int dm1 = 0;
        int dm2 = 0;
        int dm3 = 0;
        int dm4 = 0;
        //在option表里，根据questionId进行分组，找到每一个问题对应的最高分
        List<Map<Integer, Integer>> maxScore = testSoulMapper.getMaxScore();
        //遍历每一个回答
        for (Answers a : answers) {
            Integer questionId = Integer.valueOf(a.getQuestionId());
            //找每道题对应的维度类型
            int d = questionForSoulService.findDimensionalityById(a.getQuestionId());
            int score = 0;
            //从maxScore的map中找当前回答的问题对应的最高分
            for (Map<Integer, Integer> map : maxScore) {
                Integer integer = map.get(QUESTION_ID);
                if(Objects.equals(integer, questionId)){
                    score = map.get(QUESTION_MAX_SCORE);
                }
            }
            //根据维度类型赋予对应的最高分
            switch (d){
                case 1:
                    dm1 += score;
                    break;
                case 2:
                    dm2 += score;
                    break;
                case 3:
                    dm3 += score;
                    break;
                case 4:
                    dm4 += score;
                    break;
            }
        }

        //计算四个维度的占比，设置到userTopic对象中
        BigDecimal amd = new BigDecimal(dm1);
        BigDecimal ad = new BigDecimal(d1);
        if(amd.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal ard = ad.divide(amd, 2, RoundingMode.HALF_UP);
            userTopic.setDimensionality1((long) ard.multiply(new BigDecimal(100)).intValue());
        }

        BigDecimal amd2 = new BigDecimal(dm2);
        BigDecimal ad2 = new BigDecimal(d2);
        if(amd2.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal ard2 = ad2.divide(amd2, 2, RoundingMode.HALF_UP);
            userTopic.setDimensionality2((long) ard2.multiply(new BigDecimal(100)).intValue());
        }

        BigDecimal amd3 = new BigDecimal(dm3);
        BigDecimal ad3 = new BigDecimal(d3);
        if(amd3.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal ard3 = ad3.divide(amd3, 2, RoundingMode.HALF_UP);
            userTopic.setDimensionality3((long) ard3.multiply(new BigDecimal(100)).intValue());
        }

        BigDecimal amd4 = new BigDecimal(dm4);
        BigDecimal ad4 = new BigDecimal(d4);
        if(amd4.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal ard4 = ad4.divide(amd4, 2, RoundingMode.HALF_UP);
            userTopic.setDimensionality4((long) ard4.multiply(new BigDecimal(100)).intValue());
        }

        //将userTopic保存到数据库中
        save(userTopic);
        return userTopic.getId();
    }

    @Override
    public ReportVo queryResult(Long id) {
        //根据id查询用户答题记录
        if(id == null){
            throw new RuntimeException(USER_ID_NOT_NULL);
        }
        UserTopic one  = lambdaQuery().eq(UserTopic::getId, id).one();
        if(one == null){
            return null;
        }
        ReportVo reportVo = new ReportVo();
        //组装conclusion和cover
        String conclusion = testSoulMapper.findConclusion(one.getResultId());
        String cover = testSoulMapper.findCover(one.getResultId());
        if(conclusion != null){
            reportVo.setConclusion(conclusion);
        }
        if(cover != null){
            reportVo.setCover(cover);
        }
        //组装四个维度
        List<DimensionsVo> list = getDimensionsVos(one);
        reportVo.setDimensions(list);

        //查找同一类型的人
        //用lambdaQuery()查找同ResultId并且UserId不等于one.getUserId()的人
        List<UserTopic> userTopicList = lambdaQuery().eq(UserTopic::getResultId, one.getResultId())
                .ne(UserTopic::getUserId, one.getUserId()).list();

        if(userTopicList.isEmpty()){
            //返回空集合
            reportVo.setSimilarYou(Collections.emptyList());
            //直接返回vo结果
            return reportVo;
        }
        //把同一类型的人的userId封装到list中
        List<Long> userIdlist = new ArrayList<>();
        userTopicList.forEach(userTopic -> {
            userIdlist.add(userTopic.getUserId());
        });

        //根据userIdlist查询用户信息的id和avatar
        List<UserInfo> userInfoList = userInfoService.selectByIds(userIdlist);
        //封装id和avater到reportVo中
        List<SimilarYouVo> userList = userInfoList.stream().map(userInfo -> {
            SimilarYouVo similarYouVo = new SimilarYouVo();
            similarYouVo.setId(Math.toIntExact(userInfo.getId()));
            similarYouVo.setAvatar(userInfo.getAvatar());
            return similarYouVo;
        }).collect(Collectors.toList());
        reportVo.setSimilarYou(userList);
        //返回vo结果
        return reportVo;
    }

    //组装四个维度信息
    private static List<DimensionsVo> getDimensionsVos(UserTopic one) {
        List<DimensionsVo> list = new ArrayList<>();
        if(one.getDimensionality1() != null){
            DimensionsVo dimensionsVo = new DimensionsVo(DIMENSIONALITY1, one.getDimensionality1()+"%");
            list.add(dimensionsVo);
        }
        if(one.getDimensionality2() != null){
            DimensionsVo dimensionsVo = new DimensionsVo(DIMENSIONALITY2, one.getDimensionality2()+"%");
            list.add(dimensionsVo);
        }
        if(one.getDimensionality3() != null){
            DimensionsVo dimensionsVo = new DimensionsVo(DIMENSIONALITY3, one.getDimensionality3()+"%");
            list.add(dimensionsVo);
        }
        if(one.getDimensionality4() != null){
            DimensionsVo dimensionsVo = new DimensionsVo(DIMENSIONALITY4, one.getDimensionality4()+"%");
            list.add(dimensionsVo);
        }
        return list;
    }
}
